﻿#include "devicemonitorheader.h"
#include "udpsocketnetworkcenter.h"

#include <qglobalconfig.h>

QMutex UdpSocketNetWorkCenter::mutex;
UdpSocketNetWorkCenter* UdpSocketNetWorkCenter::instance = nullptr;

UdpSocketNetWorkCenter *UdpSocketNetWorkCenter::getInstance()
{
    if (instance == nullptr) {
        QMutexLocker locker(&mutex);
        if (instance == nullptr) {
            instance = new UdpSocketNetWorkCenter();
        }
    }
    return instance;
}

void UdpSocketNetWorkCenter::deleteInstance()
{
    if (instance != nullptr) {
        delete instance;
        instance = nullptr;
    }
}

void UdpSocketNetWorkCenter::sendMessage(QString &message)
{
    signal_send_message(message);
}

UdpSocketNetWorkCenter::UdpSocketNetWorkCenter(QObject *parent) : QThread(parent)
{
    qDebug() << __FUNCTION__;
    moveToThread(this); // 确保对象在自己的线程中运行
    sendPackId = 0;
    broadcastAddress = QGlobalConfig::getInstance().read("udpsocket","broadcastAddress","255.255.255.255").toString();
    broadcastPort = QGlobalConfig::getInstance().read("udpsocket","broadcastPort",3813).toUInt();
    bindProt = QGlobalConfig::getInstance().read("udpsocket","bindProt",3813).toUInt();

    connect(this,&UdpSocketNetWorkCenter::signal_send_message,this,&UdpSocketNetWorkCenter::slot_send_message,Qt::BlockingQueuedConnection);
    start();
}

UdpSocketNetWorkCenter::~UdpSocketNetWorkCenter()
{
    quit();
    wait();
    qDebug() << __FUNCTION__;
}

quint16 UdpSocketNetWorkCenter::getSendPackId()
{
    quint16 nowId = sendPackId;
    sendPackId++;
    return nowId;
}

void UdpSocketNetWorkCenter::slot_send_message(QString &message)
{
    QByteArray byteArray = message.toLatin1();
    QByteArray sendByteArray;
    sendByteArray.resize(UDP_SOCKET_FRAME_LEN);
    int sendDataLen = UDP_SOCKET_FRAME_LEN - sizeof(UdpSocketFrameHeader);
    UdpSocketFrameHeader udpSocketFrameHeader;
    udpSocketFrameHeader.packId = getSendPackId();
    udpSocketFrameHeader.packLen = byteArray.size();
    udpSocketFrameHeader.frameSerial = 0;//帧序号

    while(byteArray.size() > 0){
        udpSocketFrameHeader.dataLen = byteArray.size() > sendDataLen ? sendDataLen : byteArray.size();
        if(byteArray.size() <= sendDataLen){
            udpSocketFrameHeader.frameMark = FRAME_MARK_END;
        }else{
            udpSocketFrameHeader.frameMark = FRAME_MARK_CENTER;
        }
        memcpy(sendByteArray.data(),&udpSocketFrameHeader,sizeof(SocketFrameHeader));
        memcpy(sendByteArray.data() + sizeof(SocketFrameHeader),byteArray.data(),byteArray.size() > sendDataLen ? sendDataLen : byteArray.size());
        m_socket->writeDatagram(sendByteArray,QHostAddress(broadcastAddress),broadcastPort);
        byteArray.remove(0,byteArray.size() > sendDataLen ? sendDataLen : byteArray.size());
        udpSocketFrameHeader.frameSerial++;
        QThread::msleep(1);
    }
//    qint64 bytesSent = m_socket->writeDatagram(message.toLatin1(), QHostAddress(broadcastAddress), broadcastPort);
//    if (bytesSent == -1)
//    {
//        qDebug() << "Failed to send broadcast message";
//    }
}

void UdpSocketNetWorkCenter::run()
{
    m_socket = new QUdpSocket();
    if (m_socket->bind(QHostAddress::AnyIPv4, bindProt, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)){
        QHostAddress bindAddress = m_socket->localAddress();
        qDebug() << __FUNCTION__  << QString("UdpSocket bind on address:%1 port:%2").arg(bindAddress.toString()).arg(bindProt) << "in thread" << QThread::currentThreadId();
    } else {
        qDebug() << "Failed to bind UdpSocket";
    }
    exec(); // 进入事件循环，等待处理新连接
    m_socket->close();
    delete m_socket;
}
